package com.app.community.config.base;

import com.app.community.mapper.AuthorityMapper;
import com.app.community.mapper.LoginMapper;
import com.app.community.service.LoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

/**
 * @Date 2020/10/22 21:33
 **/

public class CustomRealm extends AuthorizingRealm {

    @Autowired
    LoginService loginService;

    @Autowired
    AuthorityMapper authorityMapper;

    // 权限认证权限认证，即登录过后，每个身份不一定，对应的所能看的页面也不一样。
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //从Shiro中获取用户名
        Object username = principals.getPrimaryPrincipal();
        //创建一个SimpleAuthorizationInfo类的对象，利用这个对象需要设置当前用户的权限信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //创建角色信息的集合
        String authority = authorityMapper.selectAuthorityFromUser(Long.parseLong(username.toString()));
        //这里应该根据账号到数据库中获取用户的所对应的所有角色信息并初始化到roles集合中
        Set<String> roles = new HashSet<>();
        String[] authorityArray = authority.split(",");
        for (int i = 0; i < authorityArray.length; i++) {
            //        判断是否包含权限
            if (authorityArray[i].equals("admin")){
                roles.add("admin");
            }
            if (authorityArray[i].equals("user")){
                roles.add("user");
            }
        }

        //设置角色信息
        simpleAuthorizationInfo.setRoles(roles);
        return simpleAuthorizationInfo;
    }


    /**
     * 身份认证。即登录通过账号和密码验证登陆人的身份信息。
     * 这里可以注入userService,为了方便演示
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 用户登录时的信息
        String userId = (String) token.getPrincipal();
        String userPwd = new String((char[]) token.getCredentials());

        //根据用户名从数据库获取密码
        String password = loginService.selectUserPassword(userId);

        // 数据库查不到密码
        if (password == null) {
            throw new UnknownAccountException();
        }

        // 根据用户输入的信息，加盐进行加密
        Object pass = new SimpleHash("MD5", userPwd, ByteSource.Util.bytes(userId), 2);

        // 比对
        if (!password.equals(pass.toString())) {
            throw new AuthenticationException();
        }

        return new SimpleAuthenticationInfo(userId, pass, ByteSource.Util.bytes(userId), getName());
    }
}
